spring security oauth2 client

您所在的位置:网站首页 cannot resolve configuration property jwttoken header spring security oauth2 client

spring security oauth2 client

2023-07-06 14:41| 来源: 网络整理| 查看: 265

在我们开发系统时,返回给前端的信息均具有统一的格式,但在使用spring security oauth2时,遇到client_id或client_secret错误时,返回信息为如下格式:

{ "timestamp": "2020-08-03T20:41:54.776+0800", "status": 401, "error": "Unauthorized", "message": "Unauthorized", "path": "/uaa/oauth/token" }

上述格式并不符合我们的开发规范,因此需要对spring security oauth2返回的信息进行处理。

通过debug发现,当通过设置header信息"Authorization Basic xeeEOnBpZzE="并提交认证时,oauth2使用的是Basic方式的认证,使用的过滤器为BasicAuthenticationFilter,最终使用BasicAuthenticationEntryPoint来生成返回信息。

经过各种尝试后,终于发现解决oauth2返回统一信息的方法。

解决方案如下:

在configure(AuthorizationServerSecurityConfigurer oauthServerSecurity) {}中新增如下代码: oauthServerSecurity.addTokenEndpointAuthenticationFilter( new BasicAuthenticationFilter(authenticationManager, customAuthenticationEntryPoint));

这样便可以覆盖默认的Basic authentication过滤器,并实现自定义的错误响应信息。

完整代码如下:

@Override public void configure(AuthorizationServerSecurityConfigurer oauthServerSecurity) { oauthServerSecurity.tokenKeyAccess("permitAll()") .checkTokenAccess("isAuthenticated()") .allowFormAuthenticationForClients(); oauthServerSecurity.addTokenEndpointAuthenticationFilter( new BasicAuthenticationFilter(authenticationManager, customAuthenticationEntryPoint)); }

自定义CustomAuthenticationEntryPoint

@Component("customAuthenticationEntryPoint") public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint { private final ObjectMapper objectMapper = new ObjectMapper(); @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException { response.setStatus(HttpStatus.OK.value()); R r = R.error(HttpStatus.UNAUTHORIZED.value(), "client_id或client_secret错误"); response.setHeader("Content-Type", "application/json;charset=utf-8"); response.getWriter().print(JSON.toJSONString(r)); response.getWriter().flush(); } }

但此处有坑:

因password模式需要注入authenticationManagerBean

@Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception{ return super.authenticationManagerBean(); }

因此,在上述代码中如果直接使用全局注入的authenticationManager会导致其在进行client_id和client_secret校验时,使用的是UserDetailsService而不是ClientDetailsService进行验证,导致最终验证失败。

因此,需要使用自定义的authenticationManager对上边有坑的代码进行改造,改造结果如下:

oauthServerSecurity.addTokenEndpointAuthenticationFilter( new BasicAuthenticationFilter(authenticationManager(), customAuthenticationEntryPoint));

哪么,如果自定义authenticationManager呢?

首先,我们需要定义一下ClientDetailsService

@Bean public AuthenticationProvider daoAuthenticationProvider() { DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider(); daoAuthenticationProvider.setUserDetailsService(new ClientDetailsUserDetailsService(customClientDetailsService())); daoAuthenticationProvider.setHideUserNotFoundExceptions(false); return daoAuthenticationProvider; }

其次,定义一个AuthenticationProvider

@Bean ClientDetailsService customClientDetailsService() { OauthClientDetailsService clientDetailsService = new OauthClientDetailsService(dataSource); clientDetailsService.setSelectClientDetailsSql(SecurityConstants.DEFAULT_SELECT_STATEMENT); clientDetailsService.setFindClientDetailsSql(SecurityConstants.DEFAULT_FIND_STATEMENT); return clientDetailsService; }

最终,定义我们的自定义authenticationManager。

@Bean public AuthenticationManager authenticationManager() { return authentication -> daoAuthenticationProvider().authenticate(authentication); }

至次,便完成了Oauth2认证服务器Unauthorized异常信息的自定义。

效果如下:

改造前:

改造后:



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3